﻿ #region Disclaimer/Info
 
 /////////////////////////////////////////////////////////////////////////////////////////////////
 //
 //   File:		ConfORMExtensions.cs
 //   Website:		http://dexterblogengine.com/
 //   Authors:		http://dexterblogengine.com/About.ashx
 //   Rev:		1
 //   Created:		19/01/2011
 //   Last edit:		19/01/2011
 //   License:		GNU Library General Public License (LGPL)
 //   File:            ConfORMExtensions.cs
 //   For updated news and information please visit http://dexterblogengine.com/
 //   Dexter is hosted to Codeplex at http://dexterblogengine.codeplex.com
 //   For any question contact info@dexterblogengine.com
 //
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 #endregion

using System;
using System.Linq.Expressions;
using System.Reflection;
using ConfOrm;
using ConfOrm.NH;
using TypeExtensions = ConfOrm.TypeExtensions;

namespace Dexter.Repository.NHibernate.Extensions {

	internal static class ConfOrmExtensions {
		
		/// <summary>
		/// Configure ConfORM with a not nullable property.
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="mapper">The mapper.</param>
		/// <param name="property">The property.</param>
		public static void NotNullable <T> ( this Mapper mapper , Expression <Func <T , object>> property ) where T : class {
			MemberInfo member = TypeExtensions.DecodeMemberAccessExpression ( property );
			Type propertyType = member.GetPropertyOrFieldType ( );
			if ( mapper.DomainInspector.IsManyToOne ( typeof ( T ) , propertyType ) ) {
				mapper.Customize <T> ( map => map.ManyToOne ( property , pm => pm.NotNullable ( true ) ) );
			}
			else {
				mapper.Customize <T> ( map => map.Property ( property , pm => pm.NotNullable ( true ) ) );
			}
		}

		/// <summary>
		/// Configure ConfORM with a unique property.
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="mapper">The mapper.</param>
		/// <param name="property">The property.</param>
		public static void Unique <T> ( this Mapper mapper , Expression <Func <T , object>> property ) where T : class {
			MemberInfo member = TypeExtensions.DecodeMemberAccessExpression ( property );
			Type propertyType = member.GetPropertyOrFieldType ( );
			if ( mapper.DomainInspector.IsManyToOne ( typeof ( T ) , propertyType ) ) {
				mapper.Customize <T> ( map => map.ManyToOne ( property , pm => pm.Unique ( true ) ) );
			}
			else {
				mapper.Customize <T> ( map => map.Property ( property , pm => pm.Unique ( true ) ) );
			}
		}

		/// <summary>
		/// Configure ConfORM with a unique key.
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="mapper">The mapper.</param>
		/// <param name="property">The property.</param>
		/// <param name="indexKey">The index key.</param>
		public static void UniqueKey <T> ( this Mapper mapper , Expression <Func <T , object>> property , string indexKey ) where T : class {
			MemberInfo member = TypeExtensions.DecodeMemberAccessExpression ( property );
			Type propertyType = member.GetPropertyOrFieldType ( );
			if ( mapper.DomainInspector.IsManyToOne ( typeof ( T ) , propertyType ) ) {
				mapper.Customize <T> ( map => map.ManyToOne ( property , pm => pm.UniqueKey ( indexKey ) ) );
			}
			else {
				mapper.Customize <T> ( map => map.Property ( property , pm => pm.UniqueKey ( indexKey ) ) );
			}
		}

		/// <summary>
		/// Configure ConfORM with a unique key.
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="mapper">The mapper.</param>
		/// <param name="indexKey">The index key.</param>
		/// <param name="properties">The properties.</param>
		public static void Index<T> ( this Mapper mapper, string indexKey, params Expression<Func<T, object>>[] properties ) where T : class {
			foreach ( var property in properties ) {
				MemberInfo member = TypeExtensions.DecodeMemberAccessExpression ( property );
				Type propertyType = member.GetPropertyOrFieldType ( );
				if (mapper.DomainInspector.IsManyToOne ( typeof ( T ), propertyType )) {
					mapper.Customize<T> ( map => map.ManyToOne ( property, pm => pm.Index ( indexKey ) ) );
				}
				else {
					mapper.Customize<T> ( map => map.Property ( property, pm => pm.Index ( indexKey ) ) );
				}
			}
		}
	}
}
